cocos-engine-external/sources/acl/compression/impl/convert.impl.h

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();
}
}