2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2026-06-06 08:42:35 +00:00

refactor: use generic loader for iw3 xanims

This commit is contained in:
Jan Laupetin
2026-06-03 22:12:47 +02:00
parent 0c22dddd0e
commit a5d61b7127
7 changed files with 1094 additions and 679 deletions
+89
View File
@@ -1,9 +1,98 @@
#include "XAnimCommon.h"
#include <algorithm>
#include <format>
#include <numeric>
#include <utility>
#include <vector>
namespace xanim
{
QuatTrack::QuatTrack()
: m_type(QuatType::NO_QUAT)
{
}
TransTrack::TransTrack()
: m_type(TransType::NO_TRANS),
m_mins({}),
m_size({}),
m_constant({})
{
}
CommonXAnimNotifyInfo::CommonXAnimNotifyInfo()
: m_time(0)
{
}
CommonXAnimNotifyInfo::CommonXAnimNotifyInfo(std::string name, const float time)
: m_name(std::move(name)),
m_time(time)
{
}
CommonDeltaTransTrack::CommonDeltaTransTrack()
: m_constant(std::nullopt),
m_small_trans(false),
m_mins({}),
m_size({})
{
}
CommonXAnimParts::CommonXAnimParts()
: m_num_frames(0),
m_looped(false),
m_frame_rate(0),
m_asset_type(0)
{
}
void CommonXAnimParts::SortBoneTracksForQuats()
{
std::vector<size_t> boneOrder(m_bone_tracks.size());
std::ranges::iota(boneOrder, 0);
std::ranges::sort(boneOrder,
[this](const size_t i0, const size_t i1)
{
const auto type0 = std::to_underlying(m_bone_tracks[i0].m_quat.m_type);
const auto type1 = std::to_underlying(m_bone_tracks[i1].m_quat.m_type);
if (type0 != type1)
return type0 < type1;
return i0 < i1;
});
std::vector<BoneTrack> boneTrackCopies(m_bone_tracks.size());
for (size_t i = 0u; i < boneOrder.size(); ++i)
{
boneTrackCopies[i] = std::move(m_bone_tracks[boneOrder[i]]);
}
m_bone_tracks = std::move(boneTrackCopies);
}
std::vector<size_t> CommonXAnimParts::GetBoneTrackOrderForTrans() const
{
// This assumes the bone tracks were already sorted for quats
std::vector<size_t> boneOrder(m_bone_tracks.size());
std::ranges::iota(boneOrder, 0);
std::ranges::sort(boneOrder,
[this](const size_t i0, const size_t i1)
{
const auto type0 = std::to_underlying(m_bone_tracks[i0].m_trans.m_type);
const auto type1 = std::to_underlying(m_bone_tracks[i1].m_trans.m_type);
if (type0 != type1)
return type0 < type1;
return i0 < i1;
});
return boneOrder;
}
std::string GetCompiledFileNameForAssetName(const std::string& assetName)
{
return std::format("xanim/{}", assetName);
+144 -1
View File
@@ -1,8 +1,151 @@
#pragma once
#include <array>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <vector>
namespace xanim
{
enum class CompiledXAnimVersion : uint8_t
{
// IW3
VERSION_17 = 17
};
enum class QuatType : uint8_t
{
NO_QUAT = 0,
HALF_QUAT = 1,
FULL_QUAT = 2,
HALF_QUAT_NO_SIZE = 3,
FULL_QUAT_NO_SIZE = 4,
};
enum class TransType : uint8_t
{
SMALL_TRANS = 5,
FULL_TRANS = 6,
TRANS_NO_SIZE = 7,
NO_TRANS = 8,
};
struct CommonXQuat
{
int16_t value[4];
};
struct CommonXQuat2
{
int16_t value[2];
};
struct CommonVec3U8
{
uint8_t value[3];
};
struct CommonVec3U16
{
uint16_t value[3];
};
class QuatTrack
{
public:
QuatTrack();
QuatType m_type;
std::vector<uint16_t> m_indices;
std::vector<CommonXQuat> m_frames;
std::vector<CommonXQuat2> m_frames2;
};
class TransTrack
{
public:
TransTrack();
TransType m_type;
std::vector<uint16_t> m_indices;
std::array<float, 3> m_mins;
std::array<float, 3> m_size;
std::vector<uint8_t> m_byte_frames;
std::vector<uint16_t> m_short_frames;
std::array<float, 3> m_constant;
};
class BoneTrack
{
public:
BoneTrack() = default;
std::string m_name;
QuatTrack m_quat;
TransTrack m_trans;
};
class CommonXAnimNotifyInfo
{
public:
CommonXAnimNotifyInfo();
CommonXAnimNotifyInfo(std::string name, float time);
std::string m_name;
float m_time;
};
class CommonDeltaQuatTrack
{
public:
CommonDeltaQuatTrack() = default;
std::vector<uint16_t> m_indices;
std::vector<CommonXQuat2> m_frames2;
};
class CommonDeltaTransTrack
{
public:
CommonDeltaTransTrack();
std::optional<std::array<float, 3>> m_constant;
bool m_small_trans;
std::vector<uint16_t> m_indices;
std::array<float, 3> m_mins;
std::array<float, 3> m_size;
std::vector<CommonVec3U8> m_frames_u8;
std::vector<CommonVec3U16> m_frames_u16;
};
class CommonXAnimDeltaTrack
{
public:
CommonXAnimDeltaTrack() = default;
std::optional<CommonDeltaQuatTrack> m_quat;
std::optional<CommonDeltaTransTrack> m_trans;
};
class CommonXAnimParts
{
public:
CommonXAnimParts();
void SortBoneTracksForQuats();
[[nodiscard]] std::vector<size_t> GetBoneTrackOrderForTrans() const;
size_t m_num_frames;
bool m_looped;
float m_frame_rate;
uint8_t m_asset_type;
std::vector<BoneTrack> m_bone_tracks;
std::vector<CommonXAnimNotifyInfo> m_notifies;
std::unique_ptr<CommonXAnimDeltaTrack> m_delta_track;
};
[[nodiscard]] std::string GetCompiledFileNameForAssetName(const std::string& assetName);
}
} // namespace xanim