Loading...
Searching...
No Matches
evaluator.h
1//
2// Copyright 2023 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7
8#ifndef PXR_BASE_TS_EVALUATOR_H
9#define PXR_BASE_TS_EVALUATOR_H
10
11#include "pxr/pxr.h"
12#include "pxr/base/ts/evalCache.h"
13#include "pxr/base/ts/spline.h"
14#include "pxr/base/ts/types.h"
15
17
18#include <vector>
19
20PXR_NAMESPACE_OPEN_SCOPE
21
29template <typename T>
31
32public:
33
36
38 TsEvaluator(TsSpline spline);
39
42 T Eval(const TsTime &time, TsSide side=TsRight) const;
43
44private:
45
46 // Vector of typed Ts_EvalCaches, one for each Bezier segment in the
47 // spline.
48 std::vector<std::shared_ptr<Ts_EvalCache<T> > > _segments;
49
50 // The spline being evaluated.
51 TsSpline _spline;
52};
53
54template <typename T>
56{
57}
58
59template <typename T>
61_spline(spline)
62{
64
65 if (spline.size() > 1) {
66
67 // Only set up eval caches when there are Bezier segments.
68 bool bezier = false;
69 for (const TsKeyFrame &kf : spline) {
70 if (kf.GetKnotType() == TsKnotBezier) {
71 bezier = true;
72 break;
73 }
74 }
75 if (!bezier) {
76 return;
77 }
78
79 _segments.reserve(spline.size() - 1);
80
81 TF_FOR_ALL(splItr, spline) {
82
83 // Create and store an eval cache for each segment (defined by a
84 // pair of adjacent keyframes) of the spline.
85
86 TsSpline::const_iterator iAfterTime = splItr;
87 iAfterTime++;
88
89 if (iAfterTime == spline.end()) {
90 break;
91 }
92
93 std::shared_ptr<Ts_EvalCache<T> > segmentCache =
94 Ts_EvalCache<T>::New(*splItr, *iAfterTime);
95
96 if (TF_VERIFY(segmentCache)) {
97 _segments.push_back(segmentCache);
98 }
99 }
100
101 }
102}
103
104template <typename T>
105T
106TsEvaluator<T>::Eval(const TsTime &time,
107 TsSide side) const
108{
109
110 // Only right-side evals can benefit from cached segments.
111 if (!_segments.empty() && side == TsRight) {
112
113 // Only use eval caches for times that are between the authored knots on
114 // the spline. Boundary extrapolation cases are evaluated directly.
115 if (time >= _spline.begin()->GetTime() &&
116 time <= _spline.rbegin()->GetTime()) {
117
118 // Get the closest keyframe <= the requested time.
119 TsSpline::const_iterator sample = _spline.lower_bound(time);
120 if (TF_VERIFY(sample != _spline.end())) {
121
122 // We will index into the _segments vector using the iterator
123 // offset of the given sample. We need another decrement if our
124 // sample is > than the requested time (we want the requested
125 // time to be in between the two keyframes contained in the eval
126 // cache entry.
127 size_t idx = sample - _spline.begin();
128 if (sample->GetTime() > time && TF_VERIFY(idx > 0)) {
129 idx--;
130 }
131
132 if (TF_VERIFY(idx < _segments.size())
133 && TF_VERIFY(_segments[idx])) {
134 return _segments[idx]->TypedEval(time);
135 }
136 }
137 }
138 }
139
140 // If we did not get a cache hit, evaluate directly on the spline.
141 if (!_spline.empty()) {
142 return _spline.Eval(time).template Get<T>();
143 }
144
145 // If we're evaluating an empty spline, fall back to zero.
146 return TsTraits<T>::zero;
147}
148
149PXR_NAMESPACE_CLOSE_SCOPE
150
151#endif
Opaque interface to a spline for evaluations using cached segments.
Definition: evaluator.h:30
T Eval(const TsTime &time, TsSide side=TsRight) const
Evaluates the spline at the given time.
Definition: evaluator.h:106
TsEvaluator()
Default constructor; falls back to empty spline.
Definition: evaluator.h:55
Specifies the value of an TsSpline object at a particular point in time.
Definition: keyFrame.h:50
Represents a spline value object.
Definition: spline.h:51
TS_API size_t size() const
\group Container API
Definition: spline.h:489
TsKeyFrameMap::const_iterator const_iterator
Our iterators are simply iterators into the contained TsKeyFrameMap We only expose const iterators be...
Definition: spline.h:469
#define TF_FOR_ALL(iter, c)
Macro for iterating over a container.
Definition: iterator.h:373
#define TF_VERIFY(cond, format,...)
Checks a condition and reports an error if it evaluates false.
Definition: diagnostic.h:266
#define TRACE_FUNCTION()
Records a timestamp when constructed and a timespan event when destructed, using the name of the func...
Definition: trace.h:26