diff --git a/src/math-util.inc b/src/math-util.inc index b7815c8f..0133a488 100644 --- a/src/math-util.inc +++ b/src/math-util.inc @@ -1,6 +1,6 @@ #pragma once -#include "prim-types.hh" +//#include "prim-types.hh" #include "value-types.hh" namespace tinyusdz { diff --git a/src/prim-types.hh b/src/prim-types.hh index 54f87382..a0d921d0 100644 --- a/src/prim-types.hh +++ b/src/prim-types.hh @@ -46,6 +46,7 @@ #include "primvar.hh" // #include "value-eval-util.hh" +#include "math-util.inc" namespace tinyusdz { @@ -1310,6 +1311,37 @@ struct TypedTimeSamples { _dirty = true; } + bool has_sample_at(const double t) const { + if (_dirty) { + update(); + } + + const auto it = std::find_if(_samples.begin(), _samples.end(), [&t](const Sample &s) { + return tinyusdz::math::is_close(t, s.t); + }); + + return (it != _samples.end()); + } + + bool get_sample_at(const double t, Sample **dst) { + if (!dst) { + return false; + } + + if (_dirty) { + update(); + } + + const auto it = std::find_if(_samples.begin(), _samples.end(), [&t](const Sample &sample) { + return math::is_close(t, sample.t); + }); + + if (it != _samples.end()) { + (*dst) = &(*it); + } + return false; + } + const std::vector &get_samples() const { if (_dirty) { update(); diff --git a/src/usdGeom.cc b/src/usdGeom.cc index 35ab05cc..a5d95a5f 100644 --- a/src/usdGeom.cc +++ b/src/usdGeom.cc @@ -305,6 +305,41 @@ bool GeomPrimvar::flatten_with_indices(const double t, std::vector *dest, con return false; } +std::vector GeomPrimvar::get_indices(const double t) const { + if (value::TimeCode(t).is_default()) { + if (has_default_indices()) { + return get_default_indices(); + } + } + + if (has_timesampled_indices()) { + std::vector indices; + if (get_timesampled_indices().get(&indices, t)) { + return indices; + } + } + + if (has_default_indices()) { + return get_default_indices(); + } + + return std::vector(); +} + +void GeomPrimvar::set_indices(const std::vector &indices, const double t) { + if (value::TimeCode(t).is_default()) { + _indices = indices; + } else { + TypedTimeSamples>::Sample *psample{nullptr}; + if (_ts_indices.get_sample_at(t, &psample)) { + // overwrite content + psample->value = indices; + } else { + _ts_indices.add_sample(t, indices); + } + } +} + template bool GeomPrimvar::flatten_with_indices(std::vector *dest, std::string *err) const { return flatten_with_indices(value::TimeCode::Default(), dest, value::TimeSampleInterpolationType::Linear, err); diff --git a/src/usdGeom.hh b/src/usdGeom.hh index a8b8ad8c..d4269b34 100644 --- a/src/usdGeom.hh +++ b/src/usdGeom.hh @@ -182,6 +182,11 @@ class GeomPrimvar { _unauthoredValuesIndex = n; } + /// + /// Get indices at specified timecode. + /// Returns empty when appropriate indices does not exist for timecode 't'. + /// + std::vector get_indices(const double t = value::TimeCode::Default()) const; const std::vector &get_default_indices() const { return _indices; @@ -266,6 +271,11 @@ class GeomPrimvar { void set_name(const std::string &name) { _name = name; } + // Set indices for specified timecode 't' + // indices will be replaced when there is an indices at timecode 't'. + void set_indices(const std::vector &indices, const double t = value::TimeCode::Default()); + + void set_default_indices(const std::vector &indices) { _indices = indices; } diff --git a/src/value-types.cc b/src/value-types.cc index d441e71c..1febf030 100644 --- a/src/value-types.cc +++ b/src/value-types.cc @@ -9,6 +9,7 @@ // #include "common-macros.inc" +#include "math-util.inc" // For compile-time map // Another candidate is frozen: https://github.com/serge-sans-paille/frozen @@ -1075,5 +1076,36 @@ bool FlexibleTypeCast(const value::Value &src, value::Value &dst) { } #endif +bool TimeSamples::has_sample_at(const double t) const { + if (_dirty) { + update(); + } + + const auto it = std::find_if(_samples.begin(), _samples.end(), [&t](const Sample &s) { + return math::is_close(t, s.t); + }); + + return (it != _samples.end()); +} + +bool TimeSamples::get_sample_at(const double t, Sample **dst) { + if (!dst) { + return false; + } + + if (_dirty) { + update(); + } + + const auto it = std::find_if(_samples.begin(), _samples.end(), [&t](const Sample &sample) { + return math::is_close(t, sample.t); + }); + + if (it != _samples.end()) { + (*dst) = &(*it); + } + return false; +} + } // namespace value } // namespace tinyusdz diff --git a/src/value-types.hh b/src/value-types.hh index 467fd6ff..5b6be1d2 100644 --- a/src/value-types.hh +++ b/src/value-types.hh @@ -2290,6 +2290,9 @@ struct TimeSamples { _dirty = false; } + bool has_sample_at(const double t) const; + bool get_sample_at(const double t, Sample **s); + nonstd::optional get_time(size_t idx) const { if (idx >= _samples.size()) { return nonstd::nullopt;