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 #include "pxr/pxr.h"
25 #include "pxr/usd/usdGeom/metrics.h"
26 #include "pxr/usd/usdGeom/tokens.h"
27
28 #include "pxr/usd/sdf/schema.h"
29 #include "pxr/usd/usd/stage.h"
30
31 #include "pxr/base/plug/plugin.h"
32 #include "pxr/base/plug/registry.h"
33
34 #include "pxr/base/tf/diagnostic.h"
35 #include "pxr/base/tf/envSetting.h"
36 #include "pxr/base/tf/staticData.h"
37 #include "pxr/base/tf/staticTokens.h"
38 #include "pxr/base/tf/token.h"
39
40 #include <cfloat>
41
42 PXR_NAMESPACE_OPEN_SCOPE
43
44
45 TF_DEFINE_PRIVATE_TOKENS(
46 _tokens,
47 (UsdGeomMetrics)
48 );
49
50 TfToken
UsdGeomGetStageUpAxis(const UsdStageWeakPtr & stage)51 UsdGeomGetStageUpAxis(const UsdStageWeakPtr &stage)
52 {
53 if (!stage){
54 TF_CODING_ERROR("Invalid UsdStage");
55 return TfToken();
56 }
57
58 // Even after we remove backwards compatibility support, we will still
59 // need to know if upAxis has been authored, since we want to provide
60 // a potentially different fallback than that of the SdfSchema.
61 if (stage->HasAuthoredMetadata(UsdGeomTokens->upAxis)){
62 TfToken axis;
63 stage->GetMetadata(UsdGeomTokens->upAxis, &axis);
64 return axis;
65 }
66
67 return UsdGeomGetFallbackUpAxis();
68 }
69
70 bool
UsdGeomSetStageUpAxis(const UsdStageWeakPtr & stage,const TfToken & axis)71 UsdGeomSetStageUpAxis(const UsdStageWeakPtr &stage, const TfToken &axis)
72 {
73 if (!stage){
74 TF_CODING_ERROR("Invalid UsdStage");
75 return false;
76 }
77
78 if (axis != UsdGeomTokens->y && axis != UsdGeomTokens->z){
79 TF_CODING_ERROR("UsdStage upAxis can only be set to \"Y\" or \"Z\", "
80 "not attempted \"%s\" on stage %s.",
81 axis.GetText(),
82 stage->GetRootLayer()->GetIdentifier().c_str());
83 return false;
84 }
85
86 return stage->SetMetadata(UsdGeomTokens->upAxis, VtValue(axis));
87 }
88
TF_MAKE_STATIC_DATA(TfToken,_fallbackUpAxis)89 TF_MAKE_STATIC_DATA(TfToken, _fallbackUpAxis)
90 {
91 TfToken upAxis;
92 std::string definingPluginName;
93 TfToken schemaFallback =
94 SdfSchema::GetInstance().GetFallback(UsdGeomTokens->upAxis)
95 .Get<TfToken>();
96
97 PlugPluginPtrVector plugs = PlugRegistry::GetInstance().GetAllPlugins();
98 TF_FOR_ALL(plugIter, plugs) {
99 PlugPluginPtr plug = *plugIter;
100 JsObject metadata = plug->GetMetadata();
101 JsValue metricsDictValue;
102 if (TfMapLookup(metadata, _tokens->UsdGeomMetrics, &metricsDictValue)){
103 if (!metricsDictValue.Is<JsObject>()) {
104 TF_CODING_ERROR(
105 "%s[%s] was not a dictionary in plugInfo.json file.",
106 plug->GetName().c_str(),
107 _tokens->UsdGeomMetrics.GetText());
108 continue;
109 }
110
111 JsObject metricsDict =
112 metricsDictValue.Get<JsObject>();
113 JsValue upAxisValue;
114 if (TfMapLookup(metricsDict,
115 UsdGeomTokens->upAxis,
116 &upAxisValue)) {
117 if (!upAxisValue.Is<std::string>()) {
118 TF_CODING_ERROR(
119 "%s[%s][%s] was not a string.",
120 plug->GetName().c_str(),
121 _tokens->UsdGeomMetrics.GetText(),
122 UsdGeomTokens->upAxis.GetText());
123 continue;
124 }
125
126 std::string axisStr = upAxisValue.Get<std::string>();
127 TfToken axisToken;
128 if (axisStr == "Y"){
129 axisToken = UsdGeomTokens->y;
130 } else if (axisStr == "Z") {
131 axisToken = UsdGeomTokens->z;
132 } else {
133 TF_CODING_ERROR(
134 "%s[%s][%s] had value \"%s\", but only \"Y\" and"
135 " \"Z\" are allowed.",
136 plug->GetName().c_str(),
137 _tokens->UsdGeomMetrics.GetText(),
138 UsdGeomTokens->upAxis.GetText(),
139 axisStr.c_str());
140 continue;
141 }
142
143 if (!upAxis.IsEmpty() && upAxis != axisToken) {
144 TF_CODING_ERROR("Plugins %s and %s provided different"
145 " fallback values for %s. Ignoring all"
146 " plugins and using schema fallback of"
147 " \"%s\"",
148 definingPluginName.c_str(),
149 plug->GetName().c_str(),
150 UsdGeomTokens->upAxis.GetText(),
151 schemaFallback.GetText());
152 *_fallbackUpAxis = schemaFallback;
153 return;
154 } else if (upAxis.IsEmpty()) {
155 definingPluginName = plug->GetName();
156 upAxis = axisToken;
157 }
158 }
159
160 }
161 }
162
163 *_fallbackUpAxis = upAxis.IsEmpty() ? schemaFallback : upAxis;
164 }
165
166 TfToken
UsdGeomGetFallbackUpAxis()167 UsdGeomGetFallbackUpAxis()
168 {
169 return *_fallbackUpAxis;
170 }
171
172
173 constexpr double UsdGeomLinearUnits::nanometers;
174 constexpr double UsdGeomLinearUnits::micrometers;
175 constexpr double UsdGeomLinearUnits::millimeters;
176 constexpr double UsdGeomLinearUnits::centimeters;
177 constexpr double UsdGeomLinearUnits::meters;
178 constexpr double UsdGeomLinearUnits::kilometers;
179 constexpr double UsdGeomLinearUnits::lightYears;
180 constexpr double UsdGeomLinearUnits::inches;
181 constexpr double UsdGeomLinearUnits::feet;
182 constexpr double UsdGeomLinearUnits::yards;
183 constexpr double UsdGeomLinearUnits::miles;
184
185 double
UsdGeomGetStageMetersPerUnit(const UsdStageWeakPtr & stage)186 UsdGeomGetStageMetersPerUnit(const UsdStageWeakPtr &stage)
187 {
188 double units = UsdGeomLinearUnits::centimeters;
189 if (!stage){
190 TF_CODING_ERROR("Invalid UsdStage");
191 return units;
192 }
193
194 stage->GetMetadata(UsdGeomTokens->metersPerUnit, &units);
195 return units;
196 }
197
198 bool
UsdGeomStageHasAuthoredMetersPerUnit(const UsdStageWeakPtr & stage)199 UsdGeomStageHasAuthoredMetersPerUnit(const UsdStageWeakPtr &stage)
200 {
201 if (!stage){
202 TF_CODING_ERROR("Invalid UsdStage");
203 return false;
204 }
205 return stage->HasAuthoredMetadata(UsdGeomTokens->metersPerUnit);
206 }
207
208 bool
UsdGeomSetStageMetersPerUnit(const UsdStageWeakPtr & stage,double metersPerUnit)209 UsdGeomSetStageMetersPerUnit(const UsdStageWeakPtr &stage,
210 double metersPerUnit)
211 {
212 if (!stage){
213 TF_CODING_ERROR("Invalid UsdStage");
214 return false;
215 }
216
217 return stage->SetMetadata(UsdGeomTokens->metersPerUnit, metersPerUnit);
218 }
219
220 bool
UsdGeomLinearUnitsAre(double authoredUnits,double standardUnits,double epsilon)221 UsdGeomLinearUnitsAre(double authoredUnits, double standardUnits,
222 double epsilon)
223 {
224 if (authoredUnits <= 0 || standardUnits <= 0){
225 return false;
226 }
227
228 const double diff = GfAbs(authoredUnits - standardUnits);
229 return (diff / authoredUnits < epsilon) && (diff / standardUnits < epsilon);
230 }
231
232
233 PXR_NAMESPACE_CLOSE_SCOPE
234
235