1 //
2 // Copyright 2016 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 #ifndef PXR_USD_USD_GEOM_XFORM_CACHE_H
25 #define PXR_USD_USD_GEOM_XFORM_CACHE_H
26 
27 #include "pxr/pxr.h"
28 #include "pxr/usd/usdGeom/api.h"
29 #include "pxr/usd/usd/attributeQuery.h"
30 #include "pxr/usd/usd/prim.h"
31 
32 #include "pxr/usd/usdGeom/xformable.h"
33 
34 #include "pxr/base/gf/matrix4d.h"
35 #include "pxr/base/tf/hashmap.h"
36 #include "pxr/base/tf/token.h"
37 
38 #include <boost/functional/hash.hpp>
39 
40 PXR_NAMESPACE_OPEN_SCOPE
41 
42 
43 /// \class UsdGeomXformCache
44 ///
45 /// A caching mechanism for transform matrices. For best performance, this
46 /// object should be reused for multiple CTM queries.
47 ///
48 /// Instances of this type can be copied, though using Swap() may result in
49 /// better performance.
50 ///
51 /// It is valid to cache prims from multiple stages in a single XformCache.
52 ///
53 /// WARNING: this class does not automatically invalidate cached values based
54 /// on changes to the stage from which values were cached. Additionally, a
55 /// separate instance of this class should be used per-thread, calling the Get*
56 /// methods from multiple threads is not safe, as they mutate internal state.
57 ///
58 class UsdGeomXformCache
59 {
60 public:
61     /// Construct a new XformCache for the specified \p time.
62     USDGEOM_API
63     explicit UsdGeomXformCache(const UsdTimeCode time);
64 
65     /// Construct a new XformCache for UsdTimeCode::Default().
66     USDGEOM_API
67     UsdGeomXformCache();
68 
69     /// Compute the transformation matrix for the given \p prim, including the
70     /// transform authored on the Prim itself, if present.
71     ///
72     /// \note This method may mutate internal cache state and is not thread
73     /// safe.
74     USDGEOM_API
75     GfMatrix4d GetLocalToWorldTransform(const UsdPrim& prim);
76 
77     /// Compute the transformation matrix for the given \p prim, but do NOT
78     /// include the transform authored on the prim itself.
79     ///
80     /// \note This method may mutate internal cache state and is not thread
81     /// safe.
82     USDGEOM_API
83     GfMatrix4d GetParentToWorldTransform(const UsdPrim& prim);
84 
85     /// Returns the local transformation of the prim. Uses the cached
86     /// XformQuery to compute the result quickly. The \p resetsXformStack
87     /// pointer must be valid. It will be set to true if \p prim resets
88     /// the transform stack.
89     /// The result of this call is cached.
90     USDGEOM_API
91     GfMatrix4d GetLocalTransformation(const UsdPrim &prim,
92                                       bool *resetsXformStack);
93 
94     /// Returns the result of concatenating all transforms beneath \p ancestor
95     /// that affect \p prim. This includes the local transform of \p prim
96     /// itself, but not the local transform of \p ancestor. If \p ancestor is
97     /// not an ancestor of \p prim, the resulting transform is the
98     /// local-to-world transformation of \p prim.
99     /// The \p resetXformTsack pointer must be valid. If any intermediate prims
100     /// reset the transform stack, \p resetXformStack will be set to true.
101     /// Intermediate transforms are cached, but the result of this call itself
102     /// is not cached.
103     USDGEOM_API
104     GfMatrix4d ComputeRelativeTransform(const UsdPrim &prim,
105                                         const UsdPrim &ancestor,
106                                         bool *resetXformStack);
107 
108     /// Whether the attribute named \p attrName, belonging to the
109     /// given \p prim affects the local transform value at the prim.
110     ///
111     /// \note This method may mutate internal cache state and is not thread
112     /// safe.
113     USDGEOM_API
114     bool IsAttributeIncludedInLocalTransform(const UsdPrim &prim,
115                                              const TfToken &attrName);
116 
117     /// Whether the local transformation value at the prim may vary over time.
118     ///
119     /// \note This method may mutate internal cache state and is not thread
120     /// safe.
121     USDGEOM_API
122     bool TransformMightBeTimeVarying(const UsdPrim &prim);
123 
124     /// Whether the xform stack is reset at the given prim.
125     ///
126     /// \note This method may mutate internal cache state and is not thread
127     /// safe.
128     USDGEOM_API
129     bool GetResetXformStack(const UsdPrim &prim);
130 
131     /// Clears all pre-cached values.
132     USDGEOM_API
133     void Clear();
134 
135     /// Use the new \p time when computing values and may clear any existing
136     /// values cached for the previous time. Setting \p time to the current time
137     /// is a no-op.
138     USDGEOM_API
139     void SetTime(UsdTimeCode time);
140 
141     /// Get the current time from which this cache is reading values.
GetTime()142     UsdTimeCode GetTime() { return _time; }
143 
144     /// Swap the contents of this XformCache with \p other.
145     USDGEOM_API
146     void Swap(UsdGeomXformCache& other);
147 
148 private:
149 
150     // Traverses backwards the hierarchy starting from prim
151     // all the way to the root and computes the ctm
152     GfMatrix4d const* _GetCtm(const UsdPrim& prim);
153 
154     // Map of cached values.
155     struct _Entry {
156         _Entry() = default;
_Entry_Entry157         _Entry(const UsdGeomXformable::XformQuery & query_,
158                const GfMatrix4d& ctm_,
159                bool ctmIsValid_)
160             : query(query_)
161             , ctm(ctm_)
162             , ctmIsValid(ctmIsValid_)
163         { }
164 
165         UsdGeomXformable::XformQuery query;
166         GfMatrix4d ctm;
167         bool ctmIsValid;
168     };
169 
170     // Helper function to get or create a new entry for a prim in the ctm cache.
171     _Entry * _GetCacheEntryForPrim(const UsdPrim &prim);
172 
173     typedef TfHashMap<UsdPrim, _Entry, boost::hash<UsdPrim> > _PrimHashMap;
174     _PrimHashMap _ctmCache;
175 
176     // The time at which this stack is querying and caching attribute values.
177     UsdTimeCode _time;
178 };
179 
180 #define USDGEOM_XFORM_CACHE_API_VERSION 1
181 
182 
183 PXR_NAMESPACE_CLOSE_SCOPE
184 
185 #endif // PXR_USD_USD_GEOM_XFORM_CACHE_H
186