cocos-engine-external/sources/acl/compression/track_array.h

273 lines
13 KiB
C++

#pragma once
////////////////////////////////////////////////////////////////////////////////
// The MIT License (MIT)
//
// Copyright (c) 2019 Nicholas Frechette & Animation Compression Library contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
////////////////////////////////////////////////////////////////////////////////
#include "acl/core/impl/compiler_utils.h"
#include "acl/core/error_result.h"
#include "acl/core/iallocator.h"
#include "acl/core/interpolation_utils.h"
#include "acl/core/track_types.h"
#include "acl/core/track_writer.h"
#include "acl/core/utils.h"
#include "acl/compression/track.h"
#include <rtm/scalarf.h>
#include <rtm/vector4f.h>
#include <cstdint>
#include <limits>
#include <type_traits>
ACL_IMPL_FILE_PRAGMA_PUSH
namespace acl
{
//////////////////////////////////////////////////////////////////////////
// An array of tracks.
// Although each track contained within is untyped, each track must have
// the same type. They must all have the same sample rate and the same
// number of samples.
//////////////////////////////////////////////////////////////////////////
class track_array
{
public:
//////////////////////////////////////////////////////////////////////////
// Constructs an empty track array.
track_array() noexcept;
//////////////////////////////////////////////////////////////////////////
// Constructs an array with the specified number of tracks.
// Tracks will be empty and untyped by default.
track_array(iallocator& allocator, uint32_t num_tracks);
//////////////////////////////////////////////////////////////////////////
// Move constructor for a track array.
track_array(track_array&& other) noexcept;
//////////////////////////////////////////////////////////////////////////
// Destroys a track array.
~track_array();
//////////////////////////////////////////////////////////////////////////
// Move assignment for a track array.
track_array& operator=(track_array&& other) noexcept;
//////////////////////////////////////////////////////////////////////////
// Returns a pointer to the allocator instance or nullptr if there is none present.
iallocator* get_allocator() const { return m_allocator; }
//////////////////////////////////////////////////////////////////////////
// Returns the number of tracks contained in this array.
uint32_t get_num_tracks() const { return m_num_tracks; }
//////////////////////////////////////////////////////////////////////////
// Returns the number of samples per track in this array.
uint32_t get_num_samples_per_track() const { return m_allocator != nullptr && m_num_tracks != 0 ? m_tracks->get_num_samples() : 0; }
//////////////////////////////////////////////////////////////////////////
// Returns the track type for tracks in this array.
track_type8 get_track_type() const { return m_allocator != nullptr && m_num_tracks != 0 ? m_tracks->get_type() : track_type8::float1f; }
//////////////////////////////////////////////////////////////////////////
// Returns the track category for tracks in this array.
track_category8 get_track_category() const { return m_allocator != nullptr && m_num_tracks != 0 ? m_tracks->get_category() : track_category8::scalarf; }
//////////////////////////////////////////////////////////////////////////
// Returns the sample rate for tracks in this array.
float get_sample_rate() const { return m_allocator != nullptr && m_num_tracks != 0 ? m_tracks->get_sample_rate() : 0.0F; }
//////////////////////////////////////////////////////////////////////////
// Returns the duration for tracks in this array.
float get_duration() const { return m_allocator != nullptr && m_num_tracks != 0 ? calculate_duration(uint32_t(m_tracks->get_num_samples()), m_tracks->get_sample_rate()) : 0.0F; }
//////////////////////////////////////////////////////////////////////////
// Returns the track name.
const string& get_name() const { return m_name; }
//////////////////////////////////////////////////////////////////////////
// Sets the track name.
void set_name(const string& name) { m_name = name.get_copy(); }
//////////////////////////////////////////////////////////////////////////
// Returns the track at the specified index.
track& operator[](uint32_t index);
//////////////////////////////////////////////////////////////////////////
// Returns the track at the specified index.
const track& operator[](uint32_t index) const;
//////////////////////////////////////////////////////////////////////////
// Iterator begin() and end() implementations.
track* begin() { return m_tracks; }
const track* begin() const { return m_tracks; }
const track* end() { return m_tracks + m_num_tracks; }
const track* end() const { return m_tracks + m_num_tracks; }
//////////////////////////////////////////////////////////////////////////
// Returns true if the track array doesn't contain any data, false otherwise.
bool is_empty() const { return m_num_tracks == 0; }
//////////////////////////////////////////////////////////////////////////
// Returns whether a track array is valid or not.
// An array is valid if:
// - It is empty
// - All tracks have the same type
// - All tracks have the same number of samples
// - All tracks have the same sample rate
// - All tracks are valid
error_result is_valid() const;
//////////////////////////////////////////////////////////////////////////
// Sample all tracks within this array at the specified sample time and
// desired rounding policy. Track samples are written out using the `track_writer` provided.
template<class track_writer_type>
void sample_tracks(float sample_time, sample_rounding_policy rounding_policy, track_writer_type& writer) const;
//////////////////////////////////////////////////////////////////////////
// Sample a single track within this array at the specified sample time and
// desired rounding policy. The track sample is written out using the `track_writer` provided.
template<class track_writer_type>
void sample_track(uint32_t track_index, float sample_time, sample_rounding_policy rounding_policy, track_writer_type& writer) const;
//////////////////////////////////////////////////////////////////////////
// Returns the raw size for this track array. Note that this differs from the actual
// memory used by an instance of this class. It is meant for comparison against
// the compressed size.
uint32_t get_raw_size() const;
protected:
//////////////////////////////////////////////////////////////////////////
// We prohibit copying
track_array(const track_array&) = delete;
track_array& operator=(const track_array&) = delete;
iallocator* m_allocator; // The allocator used to allocate our tracks
track* m_tracks; // The track list
uint32_t m_num_tracks; // The number of tracks
string m_name; // An optional name
};
//////////////////////////////////////////////////////////////////////////
// A typed track array. See `track_array` for details.
//////////////////////////////////////////////////////////////////////////
template<track_type8 track_type_>
class track_array_typed final : public track_array
{
public:
//////////////////////////////////////////////////////////////////////////
// The track type.
static constexpr track_type8 type = track_type_;
//////////////////////////////////////////////////////////////////////////
// The track category.
static constexpr track_category8 category = track_traits<track_type_>::category;
//////////////////////////////////////////////////////////////////////////
// The track member type.
using track_member_type = track_typed<track_type_>;
//////////////////////////////////////////////////////////////////////////
// Constructs an empty track array.
track_array_typed() noexcept : track_array() { static_assert(sizeof(track_array_typed) == sizeof(track_array), "You cannot add member variables to this class"); }
//////////////////////////////////////////////////////////////////////////
// Constructs an array with the specified number of tracks.
// Tracks will be empty and untyped by default.
track_array_typed(iallocator& allocator, uint32_t num_tracks) : track_array(allocator, num_tracks) {}
//////////////////////////////////////////////////////////////////////////
// Move constructor for a track array.
track_array_typed(track_array_typed&& other) noexcept : track_array(static_cast<track_array&&>(other)) {}
//////////////////////////////////////////////////////////////////////////
// Destroys a track array.
~track_array_typed() = default;
//////////////////////////////////////////////////////////////////////////
// Move assignment for a track array.
track_array_typed& operator=(track_array_typed&& other) noexcept { return static_cast<track_array_typed&>(track_array::operator=(static_cast<track_array&&>(other))); }
//////////////////////////////////////////////////////////////////////////
// Returns the track type for tracks in this array.
track_type8 get_track_type() const { return type; }
//////////////////////////////////////////////////////////////////////////
// Returns the track category for tracks in this array.
track_category8 get_track_category() const { return category; }
//////////////////////////////////////////////////////////////////////////
// Returns the track at the specified index.
track_member_type& operator[](uint32_t index);
//////////////////////////////////////////////////////////////////////////
// Returns the track at the specified index.
const track_member_type& operator[](uint32_t index) const;
//////////////////////////////////////////////////////////////////////////
// Iterator begin() and end() implementations.
track_member_type* begin() { return track_cast<track_member_type>(m_tracks); }
const track_member_type* begin() const { return track_cast<track_member_type>(m_tracks); }
const track_member_type* end() { return track_cast<track_member_type>(m_tracks) + m_num_tracks; }
const track_member_type* end() const { return track_cast<track_member_type>(m_tracks) + m_num_tracks; }
};
//////////////////////////////////////////////////////////////////////////
// Casts an untyped track array into the desired track array type while asserting for safety.
template<typename track_array_type>
track_array_type& track_array_cast(track_array& track_array_);
//////////////////////////////////////////////////////////////////////////
// Casts an untyped track array into the desired track array type while asserting for safety.
template<typename track_array_type>
const track_array_type& track_array_cast(const track_array& track_array_);
//////////////////////////////////////////////////////////////////////////
// Casts an untyped track array into the desired track array type. Returns nullptr if the types
// are not compatible or if the input is nullptr.
template<typename track_array_type>
track_array_type* track_array_cast(track_array* track_array_);
//////////////////////////////////////////////////////////////////////////
// Casts an untyped track array into the desired track array type. Returns nullptr if the types
// are not compatible or if the input is nullptr.
template<typename track_array_type>
const track_array_type* track_array_cast(const track_array* track_array_);
//////////////////////////////////////////////////////////////////////////
// Create aliases for the various typed track array types.
using track_array_float1f = track_array_typed<track_type8::float1f>;
using track_array_float2f = track_array_typed<track_type8::float2f>;
using track_array_float3f = track_array_typed<track_type8::float3f>;
using track_array_float4f = track_array_typed<track_type8::float4f>;
using track_array_vector4f = track_array_typed<track_type8::vector4f>;
using track_array_qvvf = track_array_typed<track_type8::qvvf>;
}
#include "acl/compression/impl/track_array.impl.h"
ACL_IMPL_FILE_PRAGMA_POP