237 lines
8.8 KiB
C++
237 lines
8.8 KiB
C++
#pragma once
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// The MIT License (MIT)
|
|
//
|
|
// Copyright (c) 2020 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.
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Included only once from convert.h
|
|
|
|
#include "acl/compression/compress.h"
|
|
#include "acl/compression/track_array.h"
|
|
#include "acl/core/compressed_tracks.h"
|
|
#include "acl/core/error_result.h"
|
|
#include "acl/core/iallocator.h"
|
|
#include "acl/core/track_formats.h"
|
|
#include "acl/core/impl/debug_track_writer.h"
|
|
#include "acl/decompression/decompress.h"
|
|
|
|
#include <cstdint>
|
|
|
|
namespace acl
|
|
{
|
|
namespace acl_impl
|
|
{
|
|
struct raw_sampling_decompression_settings final : public decompression_settings
|
|
{
|
|
// Disable normalization. This is only safe if we know the input data is already normalized!
|
|
static constexpr bool normalize_rotations() { return false; }
|
|
};
|
|
}
|
|
|
|
inline error_result convert_track_list(iallocator& allocator, const track_array& track_list, compressed_tracks*& out_compressed_tracks)
|
|
{
|
|
compression_settings settings = get_raw_compression_settings();
|
|
|
|
qvvf_transform_error_metric error_metric;
|
|
settings.error_metric = &error_metric;
|
|
|
|
// Include all the metadata
|
|
settings.include_track_list_name = true;
|
|
settings.include_track_names = true;
|
|
settings.include_parent_track_indices = true;
|
|
settings.include_track_descriptions = true;
|
|
|
|
output_stats stats;
|
|
return compress_track_list(allocator, track_list, settings, out_compressed_tracks, stats);
|
|
}
|
|
|
|
inline error_result convert_track_list(iallocator& allocator, const compressed_tracks& tracks, track_array& out_track_list)
|
|
{
|
|
error_result error = tracks.is_valid(false);
|
|
if (error.any())
|
|
return error;
|
|
|
|
const uint32_t num_tracks = tracks.get_num_tracks();
|
|
const track_type8 track_type = tracks.get_track_type();
|
|
const uint32_t num_samples = tracks.get_num_samples_per_track();
|
|
const float sample_rate = tracks.get_sample_rate();
|
|
const float duration = tracks.get_duration();
|
|
|
|
track_array result(allocator, num_tracks);
|
|
result.set_name(string(allocator, tracks.get_name()));
|
|
|
|
// Setup our track metadata and allocate memory
|
|
bool success = true;
|
|
for (uint32_t track_index = 0; track_index < num_tracks; ++track_index)
|
|
{
|
|
track& track_ = result[track_index];
|
|
|
|
track_desc_scalarf desc_scalar;
|
|
track_desc_transformf desc_transform;
|
|
|
|
bool got_description = false;
|
|
switch (track_type)
|
|
{
|
|
case track_type8::float1f:
|
|
got_description = tracks.get_track_description(track_index, desc_scalar);
|
|
track_ = track_float1f::make_reserve(desc_scalar, allocator, num_samples, sample_rate);
|
|
break;
|
|
case track_type8::float2f:
|
|
got_description = tracks.get_track_description(track_index, desc_scalar);
|
|
track_ = track_float2f::make_reserve(desc_scalar, allocator, num_samples, sample_rate);
|
|
break;
|
|
case track_type8::float3f:
|
|
got_description = tracks.get_track_description(track_index, desc_scalar);
|
|
track_ = track_float3f::make_reserve(desc_scalar, allocator, num_samples, sample_rate);
|
|
break;
|
|
case track_type8::float4f:
|
|
got_description = tracks.get_track_description(track_index, desc_scalar);
|
|
track_ = track_float4f::make_reserve(desc_scalar, allocator, num_samples, sample_rate);
|
|
break;
|
|
case track_type8::vector4f:
|
|
got_description = tracks.get_track_description(track_index, desc_scalar);
|
|
track_ = track_vector4f::make_reserve(desc_scalar, allocator, num_samples, sample_rate);
|
|
break;
|
|
case track_type8::qvvf:
|
|
got_description = tracks.get_track_description(track_index, desc_transform);
|
|
track_ = track_qvvf::make_reserve(desc_transform, allocator, num_samples, sample_rate);
|
|
break;
|
|
default:
|
|
ACL_ASSERT(false, "Unexpected track type");
|
|
break;
|
|
}
|
|
|
|
success &= got_description;
|
|
|
|
track_.set_name(string(allocator, tracks.get_track_name(track_index)));
|
|
}
|
|
|
|
if (!success)
|
|
return error_result("Metadata was missing from the input");
|
|
|
|
// Disable floating point exceptions since decompression assumes it
|
|
scope_disable_fp_exceptions fp_off;
|
|
|
|
// Decompress and populate our track data
|
|
const acl_impl::tracks_header& header = acl_impl::get_tracks_header(tracks);
|
|
if (header.get_rotation_format() == rotation_format8::quatf_full && header.get_translation_format() == vector_format8::vector3f_full && header.get_scale_format() == vector_format8::vector3f_full)
|
|
{
|
|
// Our input data uses full precision, retain it
|
|
decompression_context<acl_impl::raw_sampling_decompression_settings> context;
|
|
context.initialize(tracks);
|
|
|
|
acl_impl::debug_track_writer writer(allocator, track_type, num_tracks);
|
|
|
|
for (uint32_t sample_index = 0; sample_index < num_samples; ++sample_index)
|
|
{
|
|
const float sample_time = rtm::scalar_min(float(sample_index) / sample_rate, duration);
|
|
|
|
// Round to nearest to land directly on a sample
|
|
context.seek(sample_time, sample_rounding_policy::nearest);
|
|
|
|
context.decompress_tracks(writer);
|
|
|
|
for (uint32_t track_index = 0; track_index < num_tracks; ++track_index)
|
|
{
|
|
track& track_ = result[track_index];
|
|
|
|
switch (track_type)
|
|
{
|
|
case track_type8::float1f:
|
|
*reinterpret_cast<float*>(track_[sample_index]) = writer.read_float1(track_index);
|
|
break;
|
|
case track_type8::float2f:
|
|
rtm::vector_store2(writer.read_float2(track_index), reinterpret_cast<rtm::float2f*>(track_[sample_index]));
|
|
break;
|
|
case track_type8::float3f:
|
|
rtm::vector_store3(writer.read_float3(track_index), reinterpret_cast<rtm::float3f*>(track_[sample_index]));
|
|
break;
|
|
case track_type8::float4f:
|
|
rtm::vector_store(writer.read_float4(track_index), reinterpret_cast<rtm::float4f*>(track_[sample_index]));
|
|
break;
|
|
case track_type8::vector4f:
|
|
*reinterpret_cast<rtm::vector4f*>(track_[sample_index]) = writer.read_vector4(track_index);
|
|
break;
|
|
case track_type8::qvvf:
|
|
*reinterpret_cast<rtm::qvvf*>(track_[sample_index]) = writer.read_qvv(track_index);
|
|
break;
|
|
default:
|
|
ACL_ASSERT(false, "Unexpected track type");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
decompression_context<decompression_settings> context;
|
|
context.initialize(tracks);
|
|
|
|
acl_impl::debug_track_writer writer(allocator, track_type, num_tracks);
|
|
|
|
for (uint32_t sample_index = 0; sample_index < num_samples; ++sample_index)
|
|
{
|
|
const float sample_time = rtm::scalar_min(float(sample_index) / sample_rate, duration);
|
|
|
|
// Round to nearest to land directly on a sample
|
|
context.seek(sample_time, sample_rounding_policy::nearest);
|
|
|
|
context.decompress_tracks(writer);
|
|
|
|
for (uint32_t track_index = 0; track_index < num_tracks; ++track_index)
|
|
{
|
|
track& track_ = result[track_index];
|
|
|
|
switch (track_type)
|
|
{
|
|
case track_type8::float1f:
|
|
*reinterpret_cast<float*>(track_[sample_index]) = writer.read_float1(track_index);
|
|
break;
|
|
case track_type8::float2f:
|
|
rtm::vector_store2(writer.read_float2(track_index), reinterpret_cast<rtm::float2f*>(track_[sample_index]));
|
|
break;
|
|
case track_type8::float3f:
|
|
rtm::vector_store3(writer.read_float3(track_index), reinterpret_cast<rtm::float3f*>(track_[sample_index]));
|
|
break;
|
|
case track_type8::float4f:
|
|
rtm::vector_store(writer.read_float4(track_index), reinterpret_cast<rtm::float4f*>(track_[sample_index]));
|
|
break;
|
|
case track_type8::vector4f:
|
|
*reinterpret_cast<rtm::vector4f*>(track_[sample_index]) = writer.read_vector4(track_index);
|
|
break;
|
|
case track_type8::qvvf:
|
|
*reinterpret_cast<rtm::qvvf*>(track_[sample_index]) = writer.read_qvv(track_index);
|
|
break;
|
|
default:
|
|
ACL_ASSERT(false, "Unexpected track type");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
out_track_list = std::move(result);
|
|
return error_result();
|
|
}
|
|
}
|