273 lines
13 KiB
C++
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
|