mirror of
https://github.com/lighttransport/tinyusdz.git
synced 2026-01-18 01:11:17 +01:00
Add move semantics to set_timesamples and bool array dedup support
- Fix set_timesamples move overloads in prim-types.hh to use std::move() - Add std::move() at call sites in ascii-parser.cc and scene-access.cc - Add _dedup_bool_array cache in crate-reader.hh for bool array dedup - Add add_dedup_bool_array_sample_pod() method in timesamples.hh - Update UnpackTimeSampleValue_BOOL to use dedup cache for bool arrays 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -4720,17 +4720,17 @@ bool AsciiParser::ParsePrimProps(std::map<std::string, Property> *props,
|
||||
PUSH_ERROR_AND_RETURN(fmt::format("Variability mismatch. Attribute `{}` already has variability `{}`, but timeSampled value has variability `{}`.", attr_name, to_string(pattr->variability()), to_string(variability)));
|
||||
}
|
||||
|
||||
pattr->get_var().set_timesamples(ts);
|
||||
pattr->get_var().set_timesamples(std::move(ts));
|
||||
|
||||
// Set PropType to Attrib(since previously created Property may have EmptyAttrib).
|
||||
props->at(attr_name).set_property_type(Property::Type::Attrib);
|
||||
|
||||
} else {
|
||||
// new Attribute
|
||||
pattr = &attr;
|
||||
pattr = &attr;
|
||||
|
||||
primvar::PrimVar var;
|
||||
var.set_timesamples(ts);
|
||||
var.set_timesamples(std::move(ts));
|
||||
if (array_qual) {
|
||||
pattr->set_type_name(type_name + "[]");
|
||||
} else {
|
||||
|
||||
@@ -869,20 +869,47 @@ bool CrateReader::UnpackTimeSampleValue_BOOL(double t,
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ReadArray(&v_uint8)) {
|
||||
PUSH_ERROR_AND_RETURN_TAG(kTag, "Failed to read bool array.");
|
||||
}
|
||||
// Check deduplication cache for bool array
|
||||
auto it = _dedup_bool_array.find(rep);
|
||||
if (it != _dedup_bool_array.end()) {
|
||||
// Reuse cached array via ref_index
|
||||
size_t ref_index = it->second;
|
||||
DCOUT("Reusing cached BOOL array at sample index " << ref_index);
|
||||
|
||||
// Convert uint8_t array to bool array
|
||||
std::vector<bool> v_bool;
|
||||
v_bool.reserve(v_uint8.size());
|
||||
for (uint8_t val : v_uint8) {
|
||||
v_bool.push_back(val != 0);
|
||||
}
|
||||
if (dst.is_using_pod()) {
|
||||
if (!dst.add_dedup_bool_array_sample_pod(t, ref_index, &_err)) {
|
||||
PUSH_ERROR_AND_RETURN_TAG(kTag, "Failed to add dedup sample to TimeSamples.");
|
||||
}
|
||||
} else {
|
||||
PUSH_ERROR_AND_RETURN_TAG(kTag, "Non-POD path not supported for bool dedup.");
|
||||
}
|
||||
} else {
|
||||
// First occurrence - read and cache array
|
||||
if (!ReadArray(&v_uint8)) {
|
||||
PUSH_ERROR_AND_RETURN_TAG(kTag, "Failed to read bool array.");
|
||||
}
|
||||
|
||||
if (!add_array_sample_to_timesamples<bool>(&dst, t, v_bool, &_err,
|
||||
expected_total_samples)) {
|
||||
PUSH_ERROR_AND_RETURN_TAG(kTag, "Failed to add sample to TimeSamples.");
|
||||
// Convert uint8_t array to bool array
|
||||
std::vector<bool> v_bool;
|
||||
v_bool.reserve(v_uint8.size());
|
||||
for (uint8_t val : v_uint8) {
|
||||
v_bool.push_back(val != 0);
|
||||
}
|
||||
|
||||
if (dst.is_using_pod()) {
|
||||
// Store current index before adding
|
||||
size_t current_index = dst.size();
|
||||
_dedup_bool_array[rep] = current_index;
|
||||
DCOUT("Caching BOOL array at sample index " << current_index);
|
||||
|
||||
if (!dst.add_array_sample_pod<bool>(t, v_bool, &_err, expected_total_samples)) {
|
||||
PUSH_ERROR_AND_RETURN_TAG(kTag, "Failed to add sample to TimeSamples.");
|
||||
}
|
||||
} else {
|
||||
if (!dst.add_sample(t, value::Value(v_bool), &_err)) {
|
||||
PUSH_ERROR_AND_RETURN_TAG(kTag, "Failed to add sample to TimeSamples.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
@@ -549,6 +549,7 @@ class CrateReader {
|
||||
|
||||
// Integer types (scalar and array)
|
||||
std::unordered_map<crate::ValueRep, bool, crate::ValueRep::Hash> _dedup_bool;
|
||||
std::unordered_map<crate::ValueRep, size_t, crate::ValueRep::Hash> _dedup_bool_array;
|
||||
std::unordered_map<crate::ValueRep, int32_t, crate::ValueRep::Hash> _dedup_int32;
|
||||
std::unordered_map<crate::ValueRep, uint32_t, crate::ValueRep::Hash> _dedup_uint32;
|
||||
std::unordered_map<crate::ValueRep, int64_t, crate::ValueRep::Hash> _dedup_int64;
|
||||
|
||||
@@ -1278,7 +1278,7 @@ struct Animatable {
|
||||
}
|
||||
|
||||
void set_timesamples(TypedTimeSamples<T> &&ts) {
|
||||
return set(ts);
|
||||
return set(std::move(ts));
|
||||
}
|
||||
|
||||
void clear_scalar() {
|
||||
@@ -2959,7 +2959,7 @@ struct XformOp {
|
||||
|
||||
void set_timesamples(const value::TimeSamples &v) { _var.set_timesamples(v); }
|
||||
|
||||
void set_timesamples(value::TimeSamples &&v) { _var.set_timesamples(v); }
|
||||
void set_timesamples(value::TimeSamples &&v) { _var.set_timesamples(std::move(v)); }
|
||||
|
||||
bool is_timesamples() const { return _var.is_timesamples(); }
|
||||
bool has_timesamples() const { return _var.has_timesamples(); }
|
||||
|
||||
@@ -1597,6 +1597,57 @@ struct TimeSamples {
|
||||
return false; // Not using POD storage
|
||||
}
|
||||
|
||||
/// Add a deduplicated bool array sample - reuses data from an existing sample
|
||||
/// Special handling for bool since std::vector<bool> doesn't satisfy POD requirements
|
||||
/// @param t Time value for this sample
|
||||
/// @param ref_index Index of the existing sample whose data/offset to reuse
|
||||
/// @param err Optional error string
|
||||
bool add_dedup_bool_array_sample_pod(double t, size_t ref_index, std::string *err = nullptr) {
|
||||
if (_use_pod) {
|
||||
// Bool arrays are stored internally as uint8_t, but with bool type_id
|
||||
// The dedup mechanism works the same way - just reference the existing sample
|
||||
size_t new_idx = _pod_samples._times.size();
|
||||
|
||||
// Validate reference
|
||||
if (ref_index >= new_idx) {
|
||||
if (err) {
|
||||
(*err) += "Invalid ref_index in add_dedup_bool_array_sample_pod: " +
|
||||
std::to_string(ref_index) + " >= " + std::to_string(new_idx) + ".\n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (PODTimeSamples::is_dedup(_pod_samples._offsets[ref_index])) {
|
||||
if (err) {
|
||||
(*err) += "Cannot deduplicate from deduplicated sample.\n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
_pod_samples._times.push_back(t);
|
||||
_pod_samples._blocked.push_back(0); // false = 0
|
||||
|
||||
// Copy array count from the referenced sample
|
||||
size_t ref_array_count = (ref_index < _pod_samples._array_counts.size())
|
||||
? _pod_samples._array_counts[ref_index]
|
||||
: _pod_samples._array_size;
|
||||
_pod_samples._array_counts.push_back(ref_array_count);
|
||||
|
||||
// Create dedup offset: bit 63=1 (dedup), bit 62=1 (array), bits 61-0=ref_index
|
||||
uint64_t dedup_offset = PODTimeSamples::make_dedup_offset(ref_index, true);
|
||||
_pod_samples._offsets.push_back(dedup_offset);
|
||||
|
||||
_pod_samples._dirty = true;
|
||||
_dirty = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
(*err) += "Not using POD storage for dedup bool array.\n";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Typed add blocked sample for POD types (optimization path)
|
||||
template<typename T>
|
||||
bool add_blocked_sample_pod(double t, std::string *err = nullptr, size_t expected_total_samples = 0) {
|
||||
|
||||
@@ -726,7 +726,7 @@ bool ToProperty(const TypedAttribute<Animatable<T>> &input, Property &output, st
|
||||
|
||||
if (aval.value().has_timesamples()) {
|
||||
value::TimeSamples ts = ToTypelessTimeSamples(aval.value().get_timesamples());
|
||||
pvar.set_timesamples(ts);
|
||||
pvar.set_timesamples(std::move(ts));
|
||||
}
|
||||
|
||||
if (aval.value().has_value() || aval.value().has_timesamples()) {
|
||||
@@ -802,7 +802,7 @@ bool ToProperty(const TypedAttributeWithFallback<Animatable<T>> &input,
|
||||
|
||||
if (v.is_timesamples()) {
|
||||
value::TimeSamples ts = ToTypelessTimeSamples(v.get_timesamples());
|
||||
pvar.set_timesamples(ts);
|
||||
pvar.set_timesamples(std::move(ts));
|
||||
} else if (v.is_scalar()) {
|
||||
T a;
|
||||
if (v.get_scalar(&a)) {
|
||||
@@ -855,7 +855,7 @@ bool ToProperty(const TypedAttributeWithFallback<Animatable<T>> &input,
|
||||
|
||||
if (v.has_timesamples()) {
|
||||
value::TimeSamples ts = ToTypelessTimeSamples(v.get_timesamples());
|
||||
pvar.set_timesamples(ts);
|
||||
pvar.set_timesamples(std::move(ts));
|
||||
}
|
||||
|
||||
if (v.has_value()) {
|
||||
@@ -934,7 +934,7 @@ bool ToTokenProperty(const TypedAttributeWithFallback<Animatable<T>> &input,
|
||||
if (v.is_timesamples()) {
|
||||
value::TimeSamples ts =
|
||||
EnumTimeSamplesToTypelessTimeSamples(v.get_timesamples());
|
||||
pvar.set_timesamples(ts);
|
||||
pvar.set_timesamples(std::move(ts));
|
||||
} else if (v.is_scalar()) {
|
||||
T a;
|
||||
if (v.get_scalar(&a)) {
|
||||
@@ -983,7 +983,7 @@ bool ToTokenProperty(const TypedAttributeWithFallback<Animatable<T>> &input,
|
||||
if (v.has_timesamples()) {
|
||||
value::TimeSamples ts =
|
||||
EnumTimeSamplesToTypelessTimeSamples(v.get_timesamples());
|
||||
pvar.set_timesamples(ts);
|
||||
pvar.set_timesamples(std::move(ts));
|
||||
}
|
||||
|
||||
if (v.has_default()) {
|
||||
|
||||
Reference in New Issue
Block a user