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/usd/usdRender/spec.h"
25 #include "pxr/usd/usdRender/settings.h"
26 #include "pxr/usd/usdRender/product.h"
27 #include "pxr/usd/usdRender/var.h"
28 #include "pxr/usd/usdGeom/camera.h"
29 #include "pxr/base/gf/camera.h"
30 #include "pxr/base/gf/frustum.h"
31
32 PXR_NAMESPACE_OPEN_SCOPE
33
34 static void
_ReadExtraSettings(UsdPrim const & prim,VtDictionary * extraSettings,std::vector<std::string> const & namespaces)35 _ReadExtraSettings(UsdPrim const& prim, VtDictionary *extraSettings,
36 std::vector<std::string> const& namespaces)
37 {
38 std::vector<UsdAttribute> attrs = prim.GetAuthoredAttributes();
39 for (UsdAttribute attr: attrs) {
40 if (namespaces.empty()) {
41 if (attr.HasFallbackValue()) {
42 // Skip attributes built into schemas.
43 continue;
44 }
45 } else {
46 bool attrIsInRequestedNS = false;
47 for (std::string const& ns: namespaces) {
48 if (TfStringStartsWith(attr.GetName(), ns)) {
49 attrIsInRequestedNS = true;
50 break;
51 }
52 }
53 if (!attrIsInRequestedNS) {
54 continue;
55 }
56 }
57 VtValue val;
58 if (attr.Get(&val)) {
59 (*extraSettings)[attr.GetName()] = val;
60 }
61 }
62 }
63
64 template<typename T>
65 inline bool
_Get(UsdAttribute const & attr,T * val,bool sparse=false)66 _Get(UsdAttribute const &attr, T* val, bool sparse=false)
67 {
68 if (!sparse || attr.HasAuthoredValue()) {
69 return attr.Get(val);
70 }
71 return false;
72 }
73
74 static void
_ReadSettingsBase(UsdRenderSettingsBase const & base,UsdRenderSpec::Product * pd,bool sparse)75 _ReadSettingsBase(UsdRenderSettingsBase const& base,
76 UsdRenderSpec::Product *pd,
77 bool sparse)
78 {
79 SdfPathVector targets;
80 base.GetCameraRel().GetForwardedTargets(&targets);
81 if (!targets.empty()) {
82 pd->cameraPath = targets[0];
83 }
84 _Get( base.GetResolutionAttr(), &pd->resolution, sparse );
85 _Get( base.GetPixelAspectRatioAttr(), &pd->pixelAspectRatio, sparse );
86 _Get( base.GetAspectRatioConformPolicyAttr(),
87 &pd->aspectRatioConformPolicy, sparse );
88 {
89 // Convert dataWindowNDC from vec4 to range2.
90 GfVec4f dataWindowNDCVec;
91 if (_Get( base.GetDataWindowNDCAttr(), &dataWindowNDCVec, sparse )) {
92 pd->dataWindowNDC = GfRange2f(
93 GfVec2f(dataWindowNDCVec[0], dataWindowNDCVec[1]),
94 GfVec2f(dataWindowNDCVec[2], dataWindowNDCVec[3]));
95 }
96 }
97 _Get( base.GetInstantaneousShutterAttr(),
98 &pd->instantaneousShutter, sparse );
99 }
100
101 // TODO: Consolidate with CameraUtilConformedWindow(). Resolve policy
102 // name mismatches; also CameraUtil cannot compensate pixelAspectRatio.
_ApplyAspectRatioPolicy(UsdRenderSpec::Product * product)103 static void _ApplyAspectRatioPolicy(
104 UsdRenderSpec::Product *product)
105 {
106 // Gather dimensions
107 GfVec2i res = product->resolution;
108 GfVec2f size = product->apertureSize;
109 // Validate dimensions
110 if (res[0] <= 0.0 || res[1] <= 0.0 || size[0] <= 0.0 || size[1] <= 0.0) {
111 return;
112 }
113 // Compute aspect ratios
114 float resAspectRatio = float(res[0]) / float(res[1]);
115 float imageAspectRatio = product->pixelAspectRatio * resAspectRatio;
116 if (imageAspectRatio <= 0.0) {
117 return;
118 }
119 float apertureAspectRatio = size[0] / size[1];
120 // Apply policy
121 TfToken const& policy = product->aspectRatioConformPolicy;
122 enum { Width, Height, None } adjust = None;
123 if (policy == UsdRenderTokens->adjustPixelAspectRatio) {
124 product->pixelAspectRatio = apertureAspectRatio / resAspectRatio;
125 } else if (policy == UsdRenderTokens->adjustApertureHeight) {
126 adjust = Height;
127 } else if (policy == UsdRenderTokens->adjustApertureWidth) {
128 adjust = Width;
129 } else if (policy == UsdRenderTokens->expandAperture) {
130 adjust = (apertureAspectRatio > imageAspectRatio) ? Height : Width;
131 } else if (policy == UsdRenderTokens->cropAperture) {
132 adjust = (apertureAspectRatio > imageAspectRatio) ? Width : Height;
133 }
134 // Adjust aperture so that size[0] / size[1] == imageAspectRatio.
135 if (adjust == Width) {
136 product->apertureSize[0] = size[1] * imageAspectRatio;
137 } else if (adjust == Height) {
138 product->apertureSize[1] = size[0] / imageAspectRatio;
139 }
140 }
141
142 UsdRenderSpec
UsdRenderComputeSpec(UsdRenderSettings const & settings,UsdTimeCode time,std::vector<std::string> const & extraNamespaces)143 UsdRenderComputeSpec(
144 UsdRenderSettings const& settings,
145 UsdTimeCode time,
146 std::vector<std::string> const& extraNamespaces)
147 {
148 UsdRenderSpec rd;
149 UsdPrim prim = settings.GetPrim();
150 UsdStageWeakPtr stage = prim.GetStage();
151 if (!stage) {
152 TF_CODING_ERROR("Invalid stage\n");
153 return rd;
154 }
155
156 // Read shared settings as a "base product".
157 UsdRenderSpec::Product base;
158 _ReadSettingsBase(UsdRenderSettingsBase(prim), &base, false);
159 _ReadExtraSettings(prim, &base.extraSettings, extraNamespaces);
160
161 // Products
162 SdfPathVector targets;
163 settings.GetProductsRel().GetForwardedTargets(&targets);
164 for (SdfPath const& target: targets) {
165 if (UsdRenderProduct product =
166 UsdRenderProduct(stage->GetPrimAtPath(target))) {
167 UsdRenderSpec::Product pd = base;
168
169 // Read product-specific overrides to base render settings.
170 _ReadSettingsBase(UsdRenderSettingsBase(product), &pd, true);
171
172 // Read camera aperture and apply aspectRatioConformPolicy.
173 if (UsdGeomCamera cam =
174 UsdGeomCamera(stage->GetPrimAtPath(pd.cameraPath))) {
175 cam.GetHorizontalApertureAttr().Get(&pd.apertureSize[0]);
176 cam.GetVerticalApertureAttr().Get(&pd.apertureSize[1]);
177 _ApplyAspectRatioPolicy(&pd);
178 } else {
179 TF_RUNTIME_ERROR("UsdRenderSettings: Could not find camera "
180 "<%s> for product <%s>\n",
181 pd.cameraPath.GetText(), target.GetText());
182 continue;
183 }
184
185 // Read product-only settings.
186 product.GetProductTypeAttr().Get(&pd.type);
187 product.GetProductNameAttr().Get(&pd.name);
188
189 // Read render vars.
190 SdfPathVector renderVarPaths;
191 product.GetOrderedVarsRel().GetForwardedTargets(&renderVarPaths);
192 for (SdfPath const& renderVarPath: renderVarPaths ) {
193 bool foundExisting = false;
194 for (size_t i=0; i < rd.renderVars.size(); ++i) {
195 if (rd.renderVars[i].renderVarPath == renderVarPath) {
196 pd.renderVarIndices.push_back(i);
197 foundExisting = true;
198 break;
199 }
200 }
201 if (!foundExisting) {
202 UsdPrim prim = stage->GetPrimAtPath(renderVarPath);
203 if (prim.IsA<UsdRenderVar>()) {
204 UsdRenderVar rv(prim);
205 UsdRenderSpec::RenderVar rvd;
206 // Store schema-defined attributes in explicit fields.
207 rvd.renderVarPath = renderVarPath;
208 rv.GetDataTypeAttr().Get(&rvd.dataType);
209 rv.GetSourceNameAttr().Get(&rvd.sourceName);
210 rv.GetSourceTypeAttr().Get(&rvd.sourceType);
211 // Store any other custom attributes in extraSettings.
212 _ReadExtraSettings(prim, &rvd.extraSettings,
213 extraNamespaces);
214 // Record new render var.
215 pd.renderVarIndices.push_back(rd.renderVars.size());
216 rd.renderVars.emplace_back(rvd);
217 } else {
218 TF_RUNTIME_ERROR("Render product <%s> includes "
219 "render var at path <%s>, but "
220 "no suitable UsdRenderVar prim "
221 "was found. Skipping.",
222 target.GetText(),
223 renderVarPath.GetText());
224 }
225 }
226 }
227 // Store any other custom attributes in extraSettings.
228 _ReadExtraSettings(product.GetPrim(), &pd.extraSettings,
229 extraNamespaces);
230 rd.products.emplace_back(pd);
231 }
232 }
233
234 // Scene configuration
235 settings.GetMaterialBindingPurposesAttr().Get(&rd.materialBindingPurposes);
236 settings.GetIncludedPurposesAttr().Get(&rd.includedPurposes);
237 // Store any other custom attributes in extraSettings.
238 _ReadExtraSettings(prim, &rd.extraSettings, extraNamespaces);
239
240 return rd;
241 }
242
243 PXR_NAMESPACE_CLOSE_SCOPE
244