Loading...
Searching...
No Matches
evaluator.h
1//
2// Copyright 2023 Pixar
3//
4// Licensed under the Apache License, Version 2.0 (the "Apache License")
5// with the following modification; you may not use this file except in
6// compliance with the Apache License and the following modification to it:
7// Section 6. Trademarks. is deleted and replaced with:
8//
9// 6. Trademarks. This License does not grant permission to use the trade
10// names, trademarks, service marks, or product names of the Licensor
11// and its affiliates, except as required to comply with Section 4(c) of
12// the License and to reproduce the content of the NOTICE file.
13//
14// You may obtain a copy of the Apache License at
15//
16// http://www.apache.org/licenses/LICENSE-2.0
17//
18// Unless required by applicable law or agreed to in writing, software
19// distributed under the Apache License with the above modification is
20// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21// KIND, either express or implied. See the Apache License for the specific
22// language governing permissions and limitations under the Apache License.
23//
24
25#ifndef PXR_BASE_TS_EVALUATOR_H
26#define PXR_BASE_TS_EVALUATOR_H
27
28#include "pxr/pxr.h"
29#include "pxr/base/ts/evalCache.h"
30#include "pxr/base/ts/spline.h"
31#include "pxr/base/ts/types.h"
32
34
35#include <vector>
36
37PXR_NAMESPACE_OPEN_SCOPE
38
46template <typename T>
48
49public:
50
53
55 TsEvaluator(TsSpline spline);
56
59 T Eval(const TsTime &time, TsSide side=TsRight) const;
60
61private:
62
63 // Vector of typed Ts_EvalCaches, one for each Bezier segment in the
64 // spline.
65 std::vector<std::shared_ptr<Ts_EvalCache<T> > > _segments;
66
67 // The spline being evaluated.
68 TsSpline _spline;
69};
70
71template <typename T>
73{
74}
75
76template <typename T>
78_spline(spline)
79{
81
82 if (spline.size() > 1) {
83
84 // Only set up eval caches when there are Bezier segments.
85 bool bezier = false;
86 for (const TsKeyFrame &kf : spline) {
87 if (kf.GetKnotType() == TsKnotBezier) {
88 bezier = true;
89 break;
90 }
91 }
92 if (!bezier) {
93 return;
94 }
95
96 _segments.reserve(spline.size() - 1);
97
98 TF_FOR_ALL(splItr, spline) {
99
100 // Create and store an eval cache for each segment (defined by a
101 // pair of adjacent keyframes) of the spline.
102
103 TsSpline::const_iterator iAfterTime = splItr;
104 iAfterTime++;
105
106 if (iAfterTime == spline.end()) {
107 break;
108 }
109
110 std::shared_ptr<Ts_EvalCache<T> > segmentCache =
111 Ts_EvalCache<T>::New(*splItr, *iAfterTime);
112
113 if (TF_VERIFY(segmentCache)) {
114 _segments.push_back(segmentCache);
115 }
116 }
117
118 }
119}
120
121template <typename T>
122T
123TsEvaluator<T>::Eval(const TsTime &time,
124 TsSide side) const
125{
126
127 // Only right-side evals can benefit from cached segments.
128 if (!_segments.empty() && side == TsRight) {
129
130 // Only use eval caches for times that are between the authored knots on
131 // the spline. Boundary extrapolation cases are evaluated directly.
132 if (time >= _spline.begin()->GetTime() &&
133 time <= _spline.rbegin()->GetTime()) {
134
135 // Get the closest keyframe <= the requested time.
136 TsSpline::const_iterator sample = _spline.lower_bound(time);
137 if (TF_VERIFY(sample != _spline.end())) {
138
139 // We will index into the _segments vector using the iterator
140 // offset of the given sample. We need another decrement if our
141 // sample is > than the requested time (we want the requested
142 // time to be in between the two keyframes contained in the eval
143 // cache entry.
144 size_t idx = sample - _spline.begin();
145 if (sample->GetTime() > time && TF_VERIFY(idx > 0)) {
146 idx--;
147 }
148
149 if (TF_VERIFY(idx < _segments.size())
150 && TF_VERIFY(_segments[idx])) {
151 return _segments[idx]->TypedEval(time);
152 }
153 }
154 }
155 }
156
157 // If we did not get a cache hit, evaluate directly on the spline.
158 if (!_spline.empty()) {
159 return _spline.Eval(time).template Get<T>();
160 }
161
162 // If we're evaluating an empty spline, fall back to zero.
163 return TsTraits<T>::zero;
164}
165
166PXR_NAMESPACE_CLOSE_SCOPE
167
168#endif
Opaque interface to a spline for evaluations using cached segments.
Definition: evaluator.h:47
T Eval(const TsTime &time, TsSide side=TsRight) const
Evaluates the spline at the given time.
Definition: evaluator.h:123
TsEvaluator()
Default constructor; falls back to empty spline.
Definition: evaluator.h:72
Specifies the value of an TsSpline object at a particular point in time.
Definition: keyFrame.h:67
Represents a spline value object.
Definition: spline.h:68
TS_API size_t size() const
\group Container API
Definition: spline.h:506
TsKeyFrameMap::const_iterator const_iterator
Our iterators are simply iterators into the contained TsKeyFrameMap We only expose const iterators be...
Definition: spline.h:486
#define TF_FOR_ALL(iter, c)
Macro for iterating over a container.
Definition: iterator.h:390
#define TF_VERIFY(cond, format,...)
Checks a condition and reports an error if it evaluates false.
Definition: diagnostic.h:283
#define TRACE_FUNCTION()
Records a timestamp when constructed and a timespan event when destructed, using the name of the func...
Definition: trace.h:43